package com.zzh.partnersys.gateway.filter;

import com.zzh.partnersys.common.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;

    /**
     * 认证全局过滤器
     * 用于校验用户登录状态（JWT Token）
     *
     * @author zzh
     */
    @Slf4j
    @Component
    public class AuthGlobalFilter implements GlobalFilter, Ordered {

        /**
         * Token 请求头名称
         */
        private static final String TOKEN_HEADER = "Authorization";
        
        /**
         * Token 前缀
         */
        private static final String TOKEN_PREFIX = "Bearer ";

    /**
     * 不需要登录校验的路径白名单
     */
    private static final List<String> WHITE_LIST = Arrays.asList(
            // 用户登录注册相关
            "/partner/service/user/login/**",
            "/partner/service/user/register/**",
            "/partner/service/user/login/captcha",
            "/partner/service/phone/sendCode",
            "/partner/service/email/sendCode",
            "/partner/service/user/login/captcha",
            "/partner/service/user/current",
            // Swagger 文档相关
            "/partner/doc.html",
            "/partner/swagger-ui/**",
            "/partner/v3/api-docs/**",
            "/partner/webjars/**",
            "/partner/favicon.ico",
            // Knife4j 相关
            "/partner/doc.html/**",
            "/partner/swagger-resources/**",
            // MinIO 相关
            "/partner/ai/minio/**"  // 添加到白名单
    );

    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();

        // 处理 OPTIONS 预检请求（CORS）
        if ("OPTIONS".equalsIgnoreCase(request.getMethod().name())) {
            return chain.filter(exchange);
        }

        // 检查是否在白名单中
        if (isWhiteList(path)) {
            return chain.filter(exchange);
        }

        // 从请求头中获取 Token
        String authHeader = request.getHeaders().getFirst(TOKEN_HEADER);
        String token = null;
        
        if (StringUtils.hasText(authHeader) && authHeader.startsWith(TOKEN_PREFIX)) {
            token = authHeader.substring(TOKEN_PREFIX.length());
        }
        
        // 如果没有 Token，返回未授权
        if (!StringUtils.hasText(token)) {
            log.warn("请求中未携带 Token，路径: {}", path);
            return handleUnauthorized(exchange);
        }
        
        // 验证 Token
        if (!JwtUtil.validateToken(token)) {
            log.warn("Token 无效或已过期，路径: {}", path);
            return handleUnauthorized(exchange);
        }
        
        // 从 Token 中获取用户ID
        Long userId = JwtUtil.getUserIdFromToken(token);
        if (userId == null) {
            log.warn("无法从 Token 中获取用户ID，路径: {}", path);
            return handleUnauthorized(exchange);
        }
        
        log.debug("Token 验证成功，用户ID: {}, 路径: {}", userId, path);
        
        // 将用户ID放到请求头中，方便下游服务快速获取
        ServerHttpRequest modifiedRequest = request.mutate()
                .header("X-User-Id", String.valueOf(userId))
                .build();
        
        return chain.filter(exchange.mutate().request(modifiedRequest).build());
    }

    /**
     * 判断路径是否在白名单中
     */
    private boolean isWhiteList(String path) {
        return WHITE_LIST.stream().anyMatch(pattern -> pathMatcher.match(pattern, path));
    }


    /**
     * 处理未授权请求
     */
    private Mono<Void> handleUnauthorized(ServerWebExchange exchange) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);

        String json = "{\"code\":40100,\"message\":\"未登录或登录已过期，请先登录\",\"data\":null}";
        DataBufferFactory bufferFactory = response.bufferFactory();
        DataBuffer buffer = bufferFactory.wrap(json.getBytes(StandardCharsets.UTF_8));

        return response.writeWith(Mono.just(buffer));
    }

    @Override
    public int getOrder() {
        // 设置过滤器执行顺序，数字越小优先级越高
        return -100;
    }
}

